home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------
- // ^FILE: usage.c - functions to print the usage of a CmdLine
- //
- // ^DESCRIPTION:
- // This file contains the functions that are used to print the
- // command-line usage of a command that is represented by a CmdLine
- // object.
- //
- // ^HISTORY:
- // 01/09/92 Brad Appleton <brad@ssd.csd.harris.com> Created
- //
- // 03/01/93 Brad Appleton <brad@ssd.csd.harris.com>
- // - Added cmd_description field to CmdLine
- //-^^---------------------------------------------------------------------
-
- #include <iostream.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "cmdline.h"
- #include "states.h"
- #include "arglist.h"
-
- #ifdef vms
- # define getenv getsym
- extern const char * getsym(const char *);
- #endif
-
-
- //-------
- // ^FUNCTION: CmdLine::get_usage_level
- //
- // ^SYNOPSIS:
- // CmdLine::CmdUsageLevel CmdLine::get_usage_level(void)
- //
- // ^PARAMETERS:
- // NONE.
- //
- // ^DESCRIPTION:
- // Gets the usage_level that tells us how "verbose" we should be
- // when printing usage-messages. This usage_level is recorded in
- // the environment variable $USAGE_LEVEL. This variable may have the
- // following values:
- //
- // 0 : Dont print usage at all.
- // 1 : Print a terse usage message (command-line syntax only).
- // 2 : Print a verbose usage message (include argument descriptions).
- //
- // If $USAGE_LEVEL is not defined or is empty, then the default
- // usage_level is 2.
- //
- // ^REQUIREMENTS:
- //
- // ^SIDE-EFFECTS:
- // None.
- //
- // ^RETURN-VALUE:
- // The usage level to use.
- //
- // ^ALGORITHM:
- // Read the usage_level from the environment and return it.
- //-^^----
- CmdLine::CmdUsageLevel
- CmdLine::get_usage_level(void)
- {
- long level;
- char * end_scan, * level_str = ::getenv("USAGE_LEVEL");
-
- if (level_str == NULL) return VERBOSE_USAGE ;
- if (*level_str == '\0') return NO_USAGE ;
-
- level = ::strtol(level_str, &end_scan, 0);
- if (end_scan == level_str) return VERBOSE_USAGE ;
-
- switch(level) {
- case 0 : return NO_USAGE ;
- case 1 : return TERSE_USAGE ;
- default: return VERBOSE_USAGE ;
- }
- }
-
- //-------
- // ^FUNCTION: CmdLine::print_synopsis
- //
- // ^SYNOPSIS:
- // unsigned CmdLine::print_synopsis(syntax, os, cols)
- //
- // ^PARAMETERS:
- // CmdLine::CmdLineSyntax syntax;
- // -- the syntax to use (long-option, short-option, or both)
- // when printing the synopsis.
- //
- // ostream & os;
- // -- where to print.
- //
- // int cols;
- // -- the maximum width of a line.
- //
- // ^DESCRIPTION:
- // Print a command-line synopsis (the command-line syntax).
- // The synopsis should be printed to "os" using the desired syntax,
- // in lines that are no more than "cols" characters wide.
- //
- // ^REQUIREMENTS:
- //
- // ^SIDE-EFFECTS:
- // Prints on "os".
- //
- // ^RETURN-VALUE:
- // The length of the longest argument-buf that was printed.
- //
- // ^ALGORITHM:
- // It's kind of complicated so follow along!
- //-^^----
- unsigned
- CmdLine::print_synopsis(CmdLine::CmdLineSyntax syntax,
- ostream & os,
- int cols) const
- {
- #ifdef vms_style
- static char usg_prefix[] = "Format: ";
- #else
- static char usg_prefix[] = "Usage: ";
- #endif
-
- unsigned ll, positionals, longest = 0;
-
- // first print the command name
- os << usg_prefix << cmd_name ;
- ll = (cmd_name ? ::strlen(cmd_name) : 0) + (sizeof(usg_prefix) - 1);
-
- // set margin so that we always start printing arguments in a column
- // that is *past* the command name.
- //
- unsigned margin = ll + 1;
-
- // print option-syntax followed by positional parameters
- int first;
- char buf[256] ;
- for (positionals = 0 ; positionals < 2 ; positionals++) {
- first = 1;
- CmdArgListListIter list_iter(cmd_args);
- for (CmdArgList * alist = list_iter() ; alist ; alist = list_iter()) {
- CmdArgListIter iter(alist);
- for (CmdArg * cmdarg = iter() ; cmdarg ; cmdarg = iter()) {
- unsigned len, pl;
-
- // don't display hidden arguments
- if (cmdarg->syntax() & CmdArg::isHIDDEN) continue;
- if (!positionals && (cmdarg->syntax() & CmdArg::isPOS)) continue;
- if (positionals && !(cmdarg->syntax() & CmdArg::isPOS)) continue;
-
- // figure out how wide this parameter is (for printing)
- pl = len = fmt_arg(cmdarg, buf, sizeof(buf), syntax, VERBOSE_USAGE);
- if (! len) continue;
-
- if (cmdarg->syntax() & CmdArg::isLIST) pl -= 4 ; // " ..."
- if (! (cmdarg->syntax() & CmdArg::isREQ)) pl -= 2 ; // "[]"
- if (pl > longest) longest = pl;
-
- // Will this fit?
- if ((ll + len + 1) > (cols - first)) {
- os << char('\n') ;
- os.width(margin);
- os << "" ; // No - start a new line;
- ll = margin;
- } else {
- os << char(' ') ; // Yes - just throw in a space
- ++ll;
- }
- ll += len;
- os << buf;
-
- first = 0;
- } //for each cmdarg
- } //for each arg-list
- } //for each parm-type
- os << endl ;
-
- return longest ;
- }
-
-
- //-------
- // ^FUNCTION: CmdLine::print_descriptions
- //
- // ^SYNOPSIS:
- // unsigned CmdLine::print_descriptions(syntax, os, cols, longest)
- //
- // ^PARAMETERS:
- // CmdLine::CmdLineSyntax syntax;
- // -- the syntax to use (long-option, short-option, or both)
- // when printing the synopsis.
- //
- // ostream & os;
- // -- where to print.
- //
- // int cols;
- // -- the maximum width of a line.
- //
- // unsigned longest;
- // -- value returned by print_synopsis.
- //
- // ^DESCRIPTION:
- // Print a command argument descriptions (using the command-line syntax).
- // The descriptions should be printed to "os" using the desired syntax,
- // in lines that are no more than "cols" characters wide.
- //
- // ^REQUIREMENTS:
- // "longest" should correspond to a value returned by print_synopsis
- // that used the same "cmd" and syntax.
- //
- // ^SIDE-EFFECTS:
- // Prints on "os".
- //
- // ^RETURN-VALUE:
- // None.
- //
- // ^ALGORITHM:
- // Print the description for each argument.
- //-^^----
- void
- CmdLine::print_descriptions(CmdLine::CmdLineSyntax syntax,
- ostream & os,
- int cols,
- unsigned longest) const
- {
- int positionals, options = 0;
- char buf[256];
-
- for (positionals = 0 ; positionals < 2 ; positionals++) {
- CmdArgListListIter list_iter(cmd_args);
- for (CmdArgList * alist = list_iter() ; alist ; alist = list_iter()) {
- CmdArgListIter iter(alist);
- for (CmdArg * cmdarg = iter() ; cmdarg ; cmdarg = iter()) {
- // don't display hidden arguments
- if (cmdarg->syntax() & CmdArg::isHIDDEN) continue;
- if (!positionals && (cmdarg->syntax() & CmdArg::isPOS)) continue;
- if (positionals && !(cmdarg->syntax() & CmdArg::isPOS)) continue;
-
- #ifdef vms_style
- if ( !options++ ) os << "Qualifiers/Parameters:\n" ;
- #else
- if ( !options++ ) os << "Options/Arguments:\n" ;
- #endif
- if (! fmt_arg(cmdarg, buf, sizeof(buf), syntax, TERSE_USAGE)) {
- continue;
- }
- const char * description = cmdarg->description();
- if ((description == NULL) || (! *description)) continue;
- strindent(os, cols, 8, buf, (longest + 2), description);
- } //for each cmdarg
- } //for each arg-list
- } //for each parm-type
- }
-
- //-------
- // ^FUNCTION: CmdLine::usage - print command-usage
- //
- // ^SYNOPSIS:
- // void CmdLine::usage(os, usage_level);
- //
- // ^PARAMETERS:
- // ostream & os;
- // -- where to print.
- //
- // CmdLine::CmdUsageLevel usage_level;
- // -- verboseness to use.
- //
- // ^DESCRIPTION:
- // Print the usage for the given CmdLine object on "os".
- //
- // ^REQUIREMENTS:
- //
- // ^SIDE-EFFECTS:
- // Prints on "os".
- //
- // ^RETURN-VALUE:
- // None.
- //
- // ^ALGORITHM:
- // - get the usage level.
- // - determine which syntax to use
- // - get the max-columns for "os".
- // - print synopsis if required.
- // - print descriptions if required.
- //-^^----
- ostream &
- CmdLine::usage(ostream & os, CmdLine::CmdUsageLevel usage_level) const
- {
- // get user-specified usage-level
- // (if status is zero this must be an explicit request so force verbose)
- //
- if (usage_level == DEFAULT_USAGE) usage_level = get_usage_level();
- if (usage_level == NO_USAGE) return os;
-
- // determine syntax to use
- CmdLineSyntax cmd_syntax = syntax() ;
-
- // get screen size (dont know how to do this yet)
- int max_cols = 79;
-
- // print command-line synopsis
- unsigned longest = print_synopsis(cmd_syntax, os, max_cols) ;
- if (usage_level == TERSE_USAGE) return os;
-
- // now print argument descriptions
- os << "\n" ;
- print_descriptions(cmd_syntax, os, max_cols, longest) ;
-
- // now print the command-description if there is one
- if (cmd_description && *cmd_description) {
- os << "\nDescription:" << endl;
- strindent(os, max_cols, 8, "", 0, cmd_description);
- }
-
- return os;
- }
-
- ostream &
- CmdLine::usage(CmdLine::CmdUsageLevel usage_level) const {
- return usage(*cmd_err, usage_level);
- }
-
-